package fundefault

import (
	"codejy/analysis"
	"codejy/analysis/codeanalysis"
	"codejy/globalfunc"
	"codejy/store"
	"codejy/structdef"
	"codejy/typedefault"
	"codejy/utils"
	"fmt"
	"strings"
)

type PrintFunDefault struct {
	//策略名称
	Name string
}

// 注册策略
func init() {
	RegisterFunDefault(&PrintFunDefault{Name: "print"})
}

func (p *PrintFunDefault) GetName() string {
	return p.Name
}

func (p *PrintFunDefault) Execute(threadStore *structdef.ThreadStore, parameter []string) string {
	fmt.Print(PrintHandle(threadStore, parameter))
	return ""
}

// 打印处理
func PrintHandle(threadStore *structdef.ThreadStore, parameter []string) string {
	//排除字符串中的双引号
	for i := range parameter {
		codeAnalysis := codeanalysis.CodeAnalysis(threadStore, parameter[i])
		//判断是否是字符串
		if codeAnalysis == codeanalysis.STR {
			//去除双引号
			parameter[i] = parameter[i][1 : len(parameter[i])-1]
			// \n \t \r  转义
			parameter[i] = typedefault.SpecificSymbol(parameter[i])
			continue
		}
		//判断是否是实例地址,如果是实例地址,那么就获取类型toStr方法,然后执行
		if codeAnalysis == codeanalysis.InstanceAddress {
			store.NweStatusRestore(threadStore, func() string {
				threadStore.CurrentInstanceAddress = parameter[i]
				prop, _ := store.GetInstanceProp(threadStore, parameter[i])
				typeName, _ := prop["@TYPENAME@"]  //获取实例的类型名称
				scope, _ := prop["@TYPEFILEPATH@"] //获取实例的类型名称
				typeDefinition := store.GetTypeDefinition(scope.Value, typeName.Value)

				if typeDefinition != nil {
					definition, p := typeDefinition.Methods["toStr"]
					if p {
						globalfunc.ExecuteFunc("ExecuteTypeMethod", threadStore, "toStr", definition, []string{}) //执行方法
						//获取函数返回值
						variable1, _ := store.GetVariable(threadStore, "toStr")
						parameter[i] = variable1.Value
						//判断前后是否有双引号
						if strings.HasPrefix(parameter[i], "\"") && strings.HasSuffix(parameter[i], "\"") {
							parameter[i] = parameter[i][1 : len(parameter[i])-1]
						}
						return ""
					}
				}
				var pd = false
				parameter[i] = typeName.Value + ":" + "{"
				for s := range prop {
					if s == "@TYPENAME@" || s == "@TYPEFILEPATH@" {
						continue
					}
					parameter[i] += s + ":" + prop[s].Value + ","
					pd = true
				}
				if !pd {
					parameter[i] = typeName.Value + ":" + "{}"
				} else {
					parameter[i] = parameter[i][:len(parameter[i])-1] + "}"
				}
				return ""
			})
			continue
		}
		//判断是否是函数定义变量
		if codeAnalysis == codeanalysis.FUNCDEF {
			v := store.SearchFunDefinition(threadStore, parameter[i])
			var funDef = parameter[i] + "{\n"
			for _, v1 := range v.Body {
				funDef += v1.LineContent + "\n"
			}
			funDef += "}"
			parameter[i] = funDef
		}
	}
	//将parameter数组转换为字符串
	join := strings.Join(parameter, "")
	return join
}

// 容器地址打印数据,标准JSON格式
func AddrPrintJson(threadStore *structdef.ThreadStore, parameter string) string {
	var Str string
	//如果是List,那么打印出来
	value, b := typedefault.GetTypeDefaultValue[[]string](threadStore, "List", parameter)
	if b {
		Str = "["
		//以逗号分隔
		for _, v := range value {
			v = AddrPrintJson(threadStore, v)
			Str += v + ","
		}
		Str = Str[:len(Str)-1]
		Str += "]"
		return Str
	}
	//如果是Map,那么打印出来
	value1, b1 := typedefault.GetTypeDefaultValue[map[string]string](threadStore, "Map", parameter)
	if b1 {
		Str = "{"
		//以逗号分隔
		for k, v := range value1 {
			v = AddrPrintJson(threadStore, v)
			//判断v的类型,如果是字符串那么就用"包起来
			Str += k + ":" + v + ","
		}
		Str = Str[:len(Str)-1]
		Str += "}"
		return Str
	}
	//如果是Set,那么打印出来
	value2, b2 := typedefault.GetTypeDefaultValue[[]string](threadStore, "Set", parameter)
	if b2 {
		Str = "["
		//以逗号分隔
		for _, v := range value2 {
			v = AddrPrintJson(threadStore, v)
			Str += v + ","
		}
		Str = Str[:len(Str)-1]
		Str += "]"
		return Str
	}
	//如果是bytes,那么转换为实际值打印出来
	value4, b4 := typedefault.GetTypeDefaultValue[[]byte](threadStore, "Bytes", parameter)
	if b4 {
		return string(value4)
	}
	//如果是queue,那么打印出来
	value5, b5 := typedefault.GetTypeDefaultValue[*utils.Queue[string]](threadStore, "Queue", parameter)
	if b5 {
		queueDatas := value5.Values()
		Str = "["
		//以逗号分隔
		for _, v := range queueDatas {
			v = AddrPrintJson(threadStore, v)
			Str += v + ","
		}
		Str = Str[:len(Str)-1]
		Str += "]"
		return Str
	}

	//如果不是容器,那么就是普通实例地址,那么就打印内部字段和值
	if analysis.IsInstanceAddress(parameter) {
		prop, _ := store.GetInstanceProp(threadStore, parameter)
		Str = "{"
		for k, v := range prop {
			Str += k + ":" + v.Value + ","
		}
		Str = Str[:len(Str)-1]
		Str += "}"
		return Str
	}
	return parameter
}
